package com.vdf.sisconsolid.persistencemodule.dao;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class BaseDao {

	private EntityManager em;
	private EntityTransaction tx;
	private static EntityManagerFactory emf = Persistence
			.createEntityManagerFactory("persistenceTest");
	
	public BaseDao() {
		
	}

	public void persist(Object o) {
		this.initTransaction();
		em.persist(o);
		this.commitTransaction();
	}

	public Object merge(Object o) {
		this.initTransaction();
		o = em.merge(o);
		this.commitTransaction();
		return o;
	}

	public void remove(Class clazz, Long id) {
		this.initTransaction();
		em.remove(em.find(clazz, id));
		this.commitTransaction();
	}

	public Object find(Class clazz, Object o) {
		this.initTransaction();
		Object object = em.find(clazz, o);
		this.commitTransaction();
		return object;
	}
	
	public List listAll(String stringQuery, Map<String, Object> parameters) {
		return listAllWithTransaction(stringQuery, parameters);
	}

	private List listAllWithTransaction(String stringQuery, Map<String, Object> parameters) {
		this.initTransaction();
		List list = this.listAllGeneric(stringQuery, parameters);
		this.commitTransaction();
		return list;
	}
	
	public List listAllWithoutTransaction(String stringQuery, Map<String, Object> parameters) {
		List list = this.listAllGeneric(stringQuery, parameters);
		return list;
	}
	
	public List listAllWithoutTransaction(String stringQuery) {
		List list = this.listAllGeneric(stringQuery, null);
		return list;
	}
	
	private List listAllGeneric(String stringQuery, Map<String, Object> parameters) {
		Query query = em.createQuery(stringQuery);

		if (parameters != null) {
			Iterator<Entry<String, Object>> paramIterator = parameters
					.entrySet().iterator();

			while (paramIterator.hasNext()) {
				String param = paramIterator.next().getKey();
				Object value = parameters.get(param);
				query.setParameter(param, value);
			}
		}
		return query.getResultList();
	}

	public List listAll(String stringQuery) {
		return listAllWithTransaction(stringQuery, null);
	}

	public void initTransaction() {
		em = emf.createEntityManager();
		tx = em.getTransaction();
		tx.begin();
	}

	public void commitTransaction() {
		em.flush();
		tx.commit();
		em.close();
	}
	
	public void rollbackTransaction() {
		tx.rollback();
		em.close();
	}

	public EntityManager getEm() {
		return em;
	}
	
	public void closeEM() {
		if (em.isOpen()) {
			em.close();
		}
	}
}
